/**
 * @file markdown
 * @author liyong18@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import * as React from 'react';
import {
  Component,
  PropTypes
} from 'react';
import * as ReactDOM from 'react-dom';
import HTML from '../html';
import PlayGround from './play';
export default class MarkDown extends Component {
  static propTypes = {
    className: PropTypes.string,
    markDownSetLink: PropTypes.func,
    markDownDropLink: PropTypes.func
  };

  doms = [];

  constructor(props) {
    super(props);
    this.state = {
      parser: null,
      html: null
    };

    this.doRequire = this.doRequire.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.renderSchema = this.renderSchema.bind(this);
  }

  handleClick(e) {
    const href = e.target.getAttribute('href');

    if (href && href[0] !== '#' && !/^http/.test(href)) {
      e.preventDefault();
      this.props.push(href);
    }
  }

  componentDidMount() {
    this.doRequire(this.props);
    this.renderSchema();
  }

  componentDidUpdate() {
    this.renderSchema();
    const hash = this.props.location.hash;

    if (hash) {
      const dom = document.querySelector(`[name="${hash.substring(1)}"]`);
      if (dom) {
        dom.scrollIntoView();
      }
    }
  }

  componentWillUnmount() {
    this.doms.forEach(dom => ReactDOM.unmountComponentAtNode(dom));
    this.props.markDownDropLink && this.props.markDownDropLink();
  }

  componentWillReceiveProps(nextProps){
    if(nextProps.markdown && nextProps.markdown != this.props.markdown) {
      this.doRequire(nextProps);
    }
  }

  renderSchema() {
    const scripts = document.querySelectorAll('script[type="text/schema"]');

    scripts.forEach(script => {
      const props = {};
      [].slice.apply(script.attributes).forEach(item => props[item.name] = item.value);

      const dom = document.createElement('div');
      dom.setAttribute("class", "doc-play-ground");
      dom.setAttribute("style", `height: ${props.height || 200}px;`);
      script.parentNode.replaceChild(dom, script);

      this.doms.push(dom);
      ReactDOM.unstable_renderSubtreeIntoContainer(this, (
        <PlayGround
          {...this.props}
          code={script.innerText}
          scope={props.scope}
          asideWidth={props.asidewidth && parseInt(props.asidewidth, 10) || 270}
        />
      ), dom);
    });
  }

  doRequire(props) {
    if(props.markdown && !this.state.parser) {
      require(['./markdown-parser'], (parser) => {
        this.setState({parser: parser.compileMarkDownToHtml});
        let result = parser.compileMarkDownToHtml(props.markdown, props.location);

        this.setState({
          parser: parser.compileMarkDownToHtml,
          html: result.html
        });
        this.props.markDownSetLink && this.props.markDownSetLink(result.toc);
      })
    } else if (props.markdown && this.state.parser) {
      let parser = this.state.parser;
      let result = parser(props.markdown, props.location);

      this.setState({
        html: result.html
      });
      this.props.markDownSetLink && this.props.markDownSetLink(result.toc);
    }
  }

  render() {
    return this.state.parser ? (
      <div>
        <HTML key="a" className="markdown-body" html={this.state.html} />
      </div>
    ) : (
      <div className="text-center m-t-lg">
        <i className="fa fa-spinner fa-spin fa-3x fa-fw" />
      </div>
    );
  }
}